﻿using System;
using PloobsEngine.SceneControl;
using PloobsEngine.Physics;
using PloobsEngine;
using PloobsEngine.Cameras;
using PloobsEngine.Input;
using Microsoft.Xna.Framework;
using PloobsEngine.Physics.Bepu;
using PloobsEngine.Modelo;
using PloobsEngine.Material;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngineDemo3;
using PloobsEngine.Features;
using PloobsEngine.Commands;
using PloobsEngine.DataStructure;
using PloobsEngine.Light;
using Microsoft.Xna.Framework.Input;

namespace Etapa1.Screens
{
    /// <summary>
    /// Camera Screen - Mostra como usar o CameraManager
    /// </summary>
    public class CameraScreens : SceneScreen
    {
        private BepuPhysicWorld physicWorld;
        private BrutalForceWorld mundo;
        private EngineStuff engine;        
        ICamera cam;
        /// <summary>
        /// Lista circular que armazenara os nomes das cameras
        /// </summary>
        private CircularList<String> camerasNames = new CircularList<string>(3);

        public CameraScreens(EngineStuff es)
        {
            this.engine = es;
            physicWorld = new BepuPhysicWorld();
            mundo = new BrutalForceWorld(physicWorld);                                    
        }
        
        public override void LoadContent(EngineStuff es)
        {            
            InputAdvanced inp = new InputAdvanced(engine);
            engine.AddComponent(inp);

            base.LoadContent(es);            

            #region Models
            ///Mesma cena de sempre
            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\cubo", "..\\Content\\Textures\\white");
                sm.LoadModelo();
                BoxObject pi = new BoxObject(new Vector3(100, 20, 0), 1, 5,new Vector3(100, 5, 100));            
                CustomDeferred shader = new CustomDeferred(false, false, false, false);
                ///Setando alguns parametros do material
                shader.SpecularIntensity = 0.01f;
                shader.SpecularPower = 50;
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj3 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj3);
            }

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\cubo", "..\\Content\\Textures\\white");
                sm.LoadModelo();
                BoxObject pi = new BoxObject(new Vector3(90, 30, 0), 1, 10,new Vector3(1));                
                CustomDeferred shader = new CustomDeferred(false, false, false, false);
                shader.SpecularIntensity = 0;
                shader.SpecularPower = 0;
                shader.Initialize();
                IMaterial mat = new Material(shader, MaterialType.DEFERRED);
                IObject obj3 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj3);                
            }


            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\cenario");
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(Vector3.Zero, sm);                
                CustomDeferred shader = new CustomDeferred(false, false, false, false);
                shader.SpecularIntensity = 0;
                shader.SpecularPower = 0;
                shader.Initialize();
                IMaterial mat = new Material(shader, MaterialType.DEFERRED);
                IObject obj3 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj3);
            }
            

            #endregion                        
            
            LightThrowBepu lt = new LightThrowBepu(mundo, engine);         

            #region NormalLight
            ///Luzes de Sempre
            DirectionalLight ld1 = new DirectionalLight(Vector3.Left, Color.White);
            DirectionalLight ld2 = new DirectionalLight(Vector3.Right, Color.White);
            DirectionalLight ld3 = new DirectionalLight(Vector3.Backward, Color.White);
            DirectionalLight ld4 = new DirectionalLight(Vector3.Forward, Color.White);
            DirectionalLight ld5 = new DirectionalLight(Vector3.Down, Color.White);
            float li = 0.4f;
            ld1.LightIntensity = li;
            ld2.LightIntensity = li;
            ld3.LightIntensity = li;
            ld4.LightIntensity = li;
            ld5.LightIntensity = li;
            mundo.AddLight(ld1);
            mundo.AddLight(ld2);
            mundo.AddLight(ld3);
            mundo.AddLight(ld4);
            mundo.AddLight(ld5);
            #endregion

            //cam = new CameraPrimeiraPessoa(true);                        
            //cam.Name = "default";
            //mundo.CameraManager.AddCamera(cam, cam.Name);
            //mundo.CameraManager.SetActiveCamera(cam.Name);
            //camerasNames.Value = cam.Name;
            //camerasNames.Next();           
            
            ///Criando uma camera estatica
            CameraStatic camx = new CameraStatic(new Vector3(130, 100, 700), Vector3.Zero);
            ///Dando um nome a ela (para poder recupera-la depois)
            camx.Name = "default";
            ///Adiciona ao Manager (NAO ESTA SENDO ATIVADA, APENAS ADICIONADA)
            mundo.CameraManager.AddCamera(camx, camx.Name);
            ///Ativa a camera atual (AO ADICIONAR UMA CAMERA AO WORLD USANDO mundo.AddCamera(cam) A CAMERA EH AUTOMATICAMENTE ATIVADA  )
            mundo.CameraManager.SetActiveCamera(camx.Name);
            ///Adiciona a lista circular
            camerasNames.Value = camx.Name;
            camerasNames.Next();          

            ///Idem para uma segunda camera (Porem esta nao eh ativada)
            CameraStatic cam2 = new CameraStatic(new Vector3(100, 100, 100), Vector3.Zero);
            cam2.Name = "StaticCamera";            
            mundo.CameraManager.AddCamera(cam2, cam2.Name);
            camerasNames.Value = cam2.Name;
            camerasNames.Next();

            ///Idem para uma segunda terceira
            CameraStatic cam3 = new CameraStatic(new Vector3(500, 300, 300), Vector3.Zero);
            cam3.Name = "StaticCamera3";            
            mundo.CameraManager.AddCamera(cam3, cam3.Name);
            camerasNames.Value = cam3.Name;
            camerasNames.Next();

            ////Criacao de uma Tecnica
            DeferredRenderTechnic dr = new DeferredRenderTechnic(engine);            
            IRenderTechnic[] rt = new IRenderTechnic[] { dr };
            this.RenderTechnics = rt;
            this.World = mundo;

            SimpleConcreteKeyboardInputPlayable ikp = new SimpleConcreteKeyboardInputPlayable(StateKey.PRESS, Keys.Space, KeyStateChange, EntityType.CAMERA);
            BindKeyCommand bk = new BindKeyCommand(ikp, BindAction.ADD);
            CommandProcessor.getCommandProcessor().SendCommandAssyncronous(bk);            
        }

        /// <summary>
        /// Chamada qd Espaco for pressionado
        /// </summary>
        /// <param name="ipk"></param>
        void KeyStateChange(InputPlayableKeyBoard ipk)
        {
            ///TO CHANGE ONLY IN THE END OF THE MOVIMENT
            //if (mundo.CameraManager.ActiveCameraType != State.INTERPOLATING)
            //{ 
                //camerasNames.Next();
                //mundo.CameraManager.SetActiveCamera(camerasNames.Value,InterpolationType.BYSTEP, 0.005f);
                //mundo.CameraManager.SetActiveCamera(camerasNames.Value, InterpolationType.BYTIME, 3);
            //}

            ///Avanca o ponteiro da lista circular            
            camerasNames.Next();
            ///Ativa a camera que correspondente
            ///Existem dois interpoladores, Por tempo (demora um tempo fixo independententemente da distancia)
            ///e um Por Etapa, que tem uma velocidade fixa de movimentacao (independente de quanto tempo for levar)
            mundo.CameraManager.SetActiveCamera(camerasNames.Value, InterpolationType.BYTIME, 3);            
        }



    }
}

